<!DOCTYPE html>
<html>
<head>
<title>Fig. 10.1</title>
</head>
<body>
<canvas id="canvas" width="600" height="450"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// --- 1. Settings and Coordinates ---
const margin = { top: 30, right: 30, bottom: 60, left: 80 };
const width = canvas.width - margin.left - margin.right;
const height = canvas.height - margin.top - margin.bottom;
const originX = margin.left;
const originY = margin.top + height;

// Data scales
const xMax = 2.0;
const yMax = 6.0; // In major grid units. The peak of A is at 5.0.
const xScale = width / xMax;
const yScale = height / yMax;

// Helper function to convert data coords to canvas coords
function toCanvasX(x) {
    return originX + x * xScale;
}
function toCanvasY(y) {
    // y is in major grid units
    return originY - y * yScale;
}

// --- 2. Draw Grid ---
ctx.save();
ctx.beginPath();
ctx.rect(originX, margin.top, width, height);
ctx.clip(); // Clip drawing to the graph area

// Minor grid lines
ctx.strokeStyle = '#e0e0e0';
ctx.lineWidth = 0.5;
// Minor vertical lines
for (let i = 0.05; i <= xMax; i += 0.05) {
    ctx.beginPath();
    ctx.moveTo(toCanvasX(i), margin.top);
    ctx.lineTo(toCanvasX(i), originY);
    ctx.stroke();
}
// Minor horizontal lines
for (let i = 0.1; i <= yMax; i += 0.1) {
    ctx.beginPath();
    ctx.moveTo(originX, toCanvasY(i));
    ctx.lineTo(originX + width, toCanvasY(i));
    ctx.stroke();
}

// Major grid lines
ctx.strokeStyle = '#b0b0b0';
ctx.lineWidth = 1;
// Major vertical lines
for (let i = 0.5; i <= xMax; i += 0.5) {
    ctx.beginPath();
    ctx.moveTo(toCanvasX(i), margin.top);
    ctx.lineTo(toCanvasX(i), originY);
    ctx.stroke();
}
// Major horizontal lines
for (let i = 1; i <= yMax; i += 1) {
    ctx.beginPath();
    ctx.moveTo(originX, toCanvasY(i));
    ctx.lineTo(originX + width, toCanvasY(i));
    ctx.stroke();
}
ctx.restore(); // Remove clipping

// --- 3. Draw Axes ---
ctx.strokeStyle = 'black';
ctx.lineWidth = 1.5;

// Y-axis
ctx.beginPath();
ctx.moveTo(originX, originY);
ctx.lineTo(originX, margin.top - 15);
ctx.stroke();
// Arrowhead
ctx.beginPath();
ctx.moveTo(originX, margin.top - 15);
ctx.lineTo(originX - 5, margin.top - 10);
ctx.moveTo(originX, margin.top - 15);
ctx.lineTo(originX + 5, margin.top - 10);
ctx.stroke();

// X-axis
ctx.beginPath();
ctx.moveTo(originX, originY);
ctx.lineTo(originX + width, originY);
ctx.stroke();

// --- 4. Draw Labels and Ticks ---
ctx.fillStyle = 'black';
ctx.font = '16px sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'top';

// X-axis labels and ticks
ctx.lineWidth = 1.5;
for (let i = 0.5; i <= xMax; i += 0.5) {
    const x = toCanvasX(i);
    ctx.fillText(i.toFixed(1), x, originY + 8);
    ctx.beginPath();
    ctx.moveTo(x, originY);
    ctx.lineTo(x, originY + 5);
    ctx.stroke();
}
// Origin label "0"
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('0', originX, originY + 15);


// X-axis title
ctx.textAlign = 'center';
ctx.fillText('wavelength / µm', toCanvasX(xMax / 2), originY + 35);

// Y-axis title
ctx.save();
ctx.translate(margin.left - 50, margin.top + height / 2);
ctx.rotate(-Math.PI / 2);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('rate of', 0, -8);
ctx.fillText('emission', 0, 10);
ctx.restore();

// --- 5. Draw Curves ---
ctx.lineWidth = 2;

// Star A (solid)
const a_points = [ [0,0], [0.1, 0.2], [0.2, 1.8], [0.3, 3.5], [0.4, 4.6], [0.5, 5.0], [0.6, 4.8], [0.7, 4.2], [0.8, 3.6], [0.9, 3.1], [1.0, 2.8], [1.1, 2.5], [1.2, 2.3], [1.3, 2.1], [1.4, 1.95], [1.5, 1.8], [1.6, 1.65], [1.8, 1.4], [2.0, 1.2] ];
ctx.beginPath();
ctx.strokeStyle = 'black';
ctx.moveTo(toCanvasX(a_points[0][0]), toCanvasY(a_points[0][1]));
for (let i = 1; i < a_points.length; i++) {
    ctx.lineTo(toCanvasX(a_points[i][0]), toCanvasY(a_points[i][1]));
}
ctx.stroke();

// Star B (dashed)
const b_points = [ [0,0], [0.2, 0.1], [0.3, 0.5], [0.4, 1.5], [0.5, 2.2], [0.6, 2.7], [0.7, 2.8], [0.8, 2.75], [0.9, 2.6], [1.0, 2.5], [1.1, 2.35], [1.2, 2.2], [1.3, 2.1], [1.4, 2.0], [1.5, 1.9], [1.6, 1.8], [1.8, 1.6], [2.0, 1.4] ];
ctx.beginPath();
ctx.setLineDash([8, 5]);
ctx.moveTo(toCanvasX(b_points[0][0]), toCanvasY(b_points[0][1]));
for (let i = 1; i < b_points.length; i++) {
    ctx.lineTo(toCanvasX(b_points[i][0]), toCanvasY(b_points[i][1]));
}
ctx.stroke();
ctx.setLineDash([]); // Reset dash

// --- 6. Draw Text on Graph ---
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'alphabetic';
ctx.font = '16px sans-serif';

// Star A label
ctx.fillText('star A', toCanvasX(0.6), toCanvasY(4.5));

// Star B label
ctx.fillText('star B', toCanvasX(0.8), toCanvasY(2.0));

// --- 7. Figure Caption ---
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillText('Fig. 10.1', canvas.width / 2, canvas.height - 5);

</script>
</body>
</html>